<?php

  /**
   * @author Dany Mottier
   * @version 1.3.1
   */
  class Archive extends Base {
    /** @var string The filename for the archive zip file. */
    private $filename = "";

    /** @var integer The error code returned by the Open() method. */
    private $error_code = -1;

    /** @var boolean Define if the zip archive is open or not. */
    private $open = FALSE;

    /** @var ZipArchive The class reference to the archive file. */
    private $class = NULL;

    const OVERWRITE = "OVERWRITE";
    const CREATE    = "CREATE";
    const EXCL      = "EXCL";
    const CHECKCONS = "CHECKCONS";

    /**
     * Store the filename in private, create the PHP5 class to interact with the archive, and open it.<br />
     *
     * @param string $filename The filename for the archive file.
     *
     * @see Open()
     * @see <a href="http://be2.php.net/manual/en/book.zip.php">ZipArchive</a>
     */
    public function __construct($filename) {
      if (is_string($filename)) {
        $this->filename = $filename;

        $this->class = new ZipArchive();

        $this->Open();
      }
    }

    /**
     * Close the reference to the archive file.<br />
     *
     * @see Close()
     */
    public function __destruct() {
      $this->Close();
    }

    /**
     * Property used to define if the archive file is well opened.<br />
     *
     * @return boolean True if the archive file is well opened.
     */
    public function isOpen() {
      return $this->open;
    }

    /**
     * Property used to define if the ZipArchive class has been well instancied.<br />
     *
     * @return boolean True if the ZipArchive class has been well instancied.<br /><br />
     *
     * @see <a href="http://be2.php.net/manual/en/function.is-null.php">is_null()</a>
     */
    public function isNull() {
      return is_null($this->class);
    }

    /**
     * Returns the Zip archive comment.<br />
     *
     * @return mixed The Zip archive comment or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getarchivecomment.php">getArchiveComment()</a>
     */
    public function getComment() {
      if ($this->isOpen())
        return $this->class->getArchiveComment();
      else
        return FALSE;
    }

    /**
     * Returns the comment of an entry using the entry index.<br />
     *
     * @param integer $index Index of the entry.
     * @param boolean $original If $original is set to TRUE, the original
     * unchanged comment is returned.
     *
     * @return string The comment on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getcommentindex.php">getCommentIndex()</a>
     */
    public function getCommentByIndex($index, $original = FALSE) {
      if (is_int($index))
        if (is_bool($original))
          if ($this->isOpen())
            if ($original)
              return $this->class->getCommentIndex($index, ZIPARCHIVE::FL_UNCHANGED);
            else
              return $this->class->getCommentIndex($index);
          else
            return FALSE;
        else
          throw new ResourcesException("\$original parameter should be a boolean");
      else
        throw new ResourcesException("\$index parameter should be an integer");
    }

    /**
     * Returns the comment of an entry using the entry name.<br />
     *
     * @param string $name Name of the entry.
     * @param boolean $original If $original is set to TRUE, the original
     * unchanged comment is returned.
     *
     * @return string The comment on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getcommentname.php">getCommentName()</a>
     */
    public function getCommentByName($name, $original = FALSE) {
      if (is_string($name))
        if (is_bool($original))
          if ($this->isOpen())
            if ($original)
              return $this->class->getCommentName($name, ZIPARCHIVE::FL_UNCHANGED);
            else
              return $this->class->getCommentName($name);
          else
            return FALSE;
        else
          throw new ResourcesException("\$original parameter should be a boolean");
      else
        throw new ResourcesException("\$name parameter should be a string");
    }

    /**
     * Returns the error code raised when the open method is called.<br />
     *
     * @return integer A constant as an integer.
     */
    public function getErrorCode() {
      return $this->error_code;
    }

    /**
     * Returns the filename of the current zip archive.<br />
     *
     * @return string The filename of the current zip archive.
     */
    public function getFileName() {
      return $this->filename;
    }

    /**
     * Returns the name of an entry using its index.<br />
     *
     * @param integer $index Index of the entry.
     *
     * @return string The name on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getnameindex.php">getNameIndex()</a>
     */
    public function getNameByIndex($index) {
      if (is_string($index))
        if ($this->isOpen())
          return $this->class->getNameIndex($index);
        else
          return FALSE;
      else {
        throw new ResourcesException("\$index parameter should be a string");
      }
    }

    /**
     * Returns the index of the entry in the archive.<br />
     *
     * @param string $name The name of the entry to look up.
     * @param integer $flag The flags are specified by ORing the following
     * values, or 0 for none of them, ZIPARCHIVE::FL_NOCASE or
     * ZIPARCHIVE::FL_NODIR.
     *
     * @return integer The index of the entry on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-locatename.php">locateName()</a>
     */
    public function getIndexByName($name, $flag = 0) {
      if (Validator::Validate($name, Validator::STRING) &&
          Validator::Validate($flag, Validator::INTEGER))
        if ($this->isOpen())
          return $this->class->locateName($name, $flag);
        else
          return FALSE;
    }

    /**
     * Set the comment of a ZIP archive.<br />
     *
     * @param string $comment The contents of the comment.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-setarchivecomment.php">setArchiveComment()</a>
     */
    public function setComment($comment) {
      if (Validator::Validate($comment, Validator::STRING))
        if ($this->isOpen())
          return $this->class->setArchiveComment($comment);
        else
          return FALSE;
    }

    /**
     * Set the comment of an entry defined by its index.<br />
     *
     * @param integer $index Index of the entry.
     * @param string $comment The contents of the comment.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-setcommentindex.php">setCommentIndex()</a>
     */
    public function setCommentByIndex($index, $comment) {
      if (Validator::Validate($index, Validator::INTEGER) &&
          Validator::Validate($comment, Validator::STRING))
        if ($this->isOpen())
          return $this->class->setCommentIndex($index, $comment);
        else
          return FALSE;
    }

    /**
     * Set the comment of an entry defined by its name.<br />
     *
     * @param string $name Name of the entry.
     * @param string $comment The contents of the comment.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isopen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-setCommentName.php">setCommentName()</a>
     */
    public function setCommentByName($name, $comment) {
      if (Validator::Validate(array($name, $comment), Validator::STRING))
        if ($this->isOpen())
          return $this->class->setCommentName($name, $comment);
        else
          return FALSE;
    }

    /**
     * Adds a file to a ZIP archive from the given path.<br />
     *
     * @param string $filename The path to the file to add.
     * @param string $localname Local name inside ZIP archive.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-addfile.php">addFile()</a>
     */
    public function AddFile($filename, $localname = "") {
      if (Validator::Validate(array($filename, $localname), Validator::STRING))
        if ($this->isOpen())
          if (! empty($localname))
            return $this->class->addFile($filename, $localname);
          else
            return $this->class->addFile($filename);
        else
          return FALSE;
    }

    /**
     * Add a file to a ZIP archive using its contents.<br />
     *
     * @param string $localname The name of the entry to create.
     * @param string $content The contents to use to create the entry. It is
     * used in a binary safe mode.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-addfromstring.php">addFromString()</a>
     */
    public function AddFromString($localname, $content) {
      if (Validator::Validate(array($localname, $content), Validator::STRING))
        if ($this->isOpen())
          return $this->class->addFromString($localname, $content);
        else
          return FALSE;
    }

    /**
     * Close the active archive (opened or newly created).<br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-close.php">close()</a>
     */
    private function Close() {
      if ($this->isOpen())
        $this->class->close();
    }

    /**
     * Add a new directory.<br />
     *
     * @param string $dirname The directory to add.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-addemptydir.php">addEmptyDir()</a>
     */
    public function CreateDirectory($dirname) {
      if (Validator::Validate($dirname, Validator::STRING))
        if ($this->isOpen())
          return $this->class->addEmptyDir($dirname);
        else
          return FALSE;
    }

    /**
     * Delete an entry in the archive using its index.<br />
     *
     * @param integer $index Index of the entry to delete.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-deleteindex.php">deleteIndex()</a>
     */
    public function DeleteByIndex($index) {
      if (Validator::Validate($index, Validator::INTEGER))
        if ($this->isOpen())
          return $this->class->deleteIndex($index);
        else
          return FALSE;
    }

    /**
     * Delete an entry in the archive using its name.<br />
     *
     * @param string $name Name of the entry to delete.
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-deletename.php">deleteName()</a>
     */
    public function DeleteByName($name) {
      if (Validator::Validate($name, Validator::STRING))
        if ($this->isOpen())
          return $this->class->deleteName($name);
        else
          return FALSE;
    }

    /**
     * Extract the archive contents.<br />
     *
     * @param string $destination Location where to extract the files.
     * @param mixed $entries The entries to extract. It accepts either a single
     * entry name or an array of names.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-extractto.php">extractTo()</a>
     */
    public function ExtractTo($destination, $entries = NULL) {
      if (Validator::Validate($destination, Validator::INTEGER))
        if ($this->isOpen())
          if (! is_null($entries))
            return $this->class->extractTo($destination, $entries);
          else
            return $this->class->extractTo($destination);
        else
          return FALSE;
    }

    /**
     * Returns the entry contents using its index.<br />
     *
     * @param integer $index Index of the entry.
     * @param constant $flag The flags to use to open the archive.<br />
     * The following values may be ORed to it : ZIPARCHIVE::FL_UNCHANGED or
     * ZIPARCHIVE::FL_COMPRESSED
     *
     * @return mixed The contents of the entry on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getfromindex.php">getFromIndex()</a>
     */
    public function GetByIndex($index, $flag = NULL) {
      if (Validator::Validate($index, Validator::INTEGER))
        if ($this->isOpen())
          if (! is_null($flag))
            return $this->class->getFromIndex($index, $flag);
          else
            return $this->class->getFromIndex($index);
        else
          return FALSE;
    }

    /**
     * Returns the entry contents using its name.<br />
     *
     * @param string $name Name of the entry.
     * @param constant $flag The flags to use to open the archive.<br />The following
     * values may be ORed to it : ZIPARCHIVE::FL_UNCHANGED or
     * ZIPARCHIVE::FL_COMPRESSED
     *
     * @return mixed The contents of the entry on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getfromname.php">getFromName()</a>
     */
    public function GetByName($name, $flag = NULL) {
      if (Validator::Validate($name, Validator::STRING))
        if ($this->isOpen())
          if (! is_null($flag))
            return $this->class->getFromName($name, $flag);
          else
            return $this->class->getFromName($name);
        else
          return FALSE;
    }

    /**
     * Get the details of an entry defined by its index.<br />
     *
     * @param integer $index Index of the entry.
     * @param boolean $original ZIPARCHIVE::FL_UNCHANGED may be ORed to it to
     * request information about the original file in the archive, ignoring any
     * changes made.
     *
     * @return mixed An ArchiveInfo object or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-statindex.php">statIndex()</a>
     */
    public function GetInformationsByIndex($index, $original = FALSE) {
      if (Validator::Validate($index, Validator::INTEGER) &&
          Validator::Validate($original, Validator::BOOLEAN))
        if ($this->isOpen())
          if ($original)
            return new ArchiveInfo($this->class->statIndex($index, ZIPARCHIVE::FL_UNCHANGED));
          else
            return new ArchiveInfo($this->class->statIndex($index));
        else
          return FALSE;
    }

    /**
     * Get the details of an entry defined by its name.<br />
     *
     * @param string $name Name of the entry.
     * @param boolean $original The flags argument specifies how the name lookup should
     * be done.<br />Also, ZIPARCHIVE::FL_UNCHANGED may be ORed to it to request
     * information about the original file in the archive, ignoring any changes
     * made.
     *
     * @return mixed An ArchiveInfo object or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-statname.php">statName()</a>
     */
    public function GetInformationsByName($name, $original = FALSE) {
      if (Validator::Validate($name, Validator::STRING) &&
          Validator::Validate($original, Validator::BOOLEAN))
        if ($this->isOpen())
          if ($original)
            return new ArchiveInfo($this->class->statName($name, ZIPARCHIVE::FL_UNCHANGED));
          else
            return new ArchiveInfo($this->class->statName($name));
        else
          return FALSE;
    }

    /**
     * Get a file handler to the entry defined by its name (read only).<br />
     *
     * @param string $name The name of the entry to use.
     *
     * @return mixed A file pointer (resource) on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-getstream.php">getStream()</a>
     */
    public function GetStream($name) {
      if (Validator::Validate($name, Validator::STRING))
        if ($this->isOpen())
          return $this->class->getStream($name);
        else
          return FALSE;
    }

    /**
     * Open a ZIP file archive.<br />
     *
     * @param integer $mode The mode to use to open the archive. The possible
     * modes are ZIPARCHIVE::OVERWRITE, ZIPARCHIVE::CREATE, ZIPARCHIVE::EXCL or
     * ZIPARCHIVE::CHECKCONS.
     *
     * @see <a href="http://be2.php.net/manual/en/function.empty.php">empty()</a>
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-open.php">open()</a>
     */
    private function Open($mode = 0) {
      if (Validator::Validate($mode, Validator::INTEGER)) {
        if (empty($mode))
          $mode = ZIPARCHIVE::CREATE;

        $this->error_code = $this->class->open($this->filename, $mode);

        if ($this->error_code === TRUE)
          $this->open = TRUE;
      }
    }

    /**
     * Renames an entry defined by its index.<br />
     *
     * @param integer $index Index of the entry to rename.
     * @param string $new_name New name.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-renameindex.php">renameIndex()</a>
     */
    public function RenameByIndex($index, $new_name) {
      if (Validator::Validate($index, Validator::INTEGER) &&
          Validator::Validate($new_name, Validator::STRING))
        if ($this->isOpen())
          return $this->class->renameIndex($index, $new_name);
        else
          return FALSE;
    }

    /**
     * Renames an entry defined by its name.<br />
     *
     * @param string $name Name of the entry to rename.
     * @param string $new_name New name.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-renamename.php">renameName()</a>
     */
    public function RenameByName($name, $new_name) {
      if (Validator::Validate(array($name, $new_name), Validator::STRING))
        if ($this->isOpen())
          return $this->class->renameName($name, $new_name);
        else
          return FALSE;
    }

    /**
     * Undo all changes done in the archive.<br />
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-unchangeall.php">unchangeAll()</a>
     */
    public function UnchangeAll() {
      if ($this->isOpen())
        return $this->class->unchangeAll();
      else
        return FALSE;
    }

    /**
     * Revert all global changes done in the archive.<br />
     *
     * @deprecated
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-unchangearchive.php">unchangeArchive()</a>
     */
    public function UnchangeComments() {
      if ($this->isOpen())
        return $this->class->unchangeArchive();
      else
        return FALSE;
    }

    /**
     * Revert all changes done to an entry at the given index.<br />
     *
     * @param integer $index Index of the entry.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-unchangeindex.php">unchangeIndex()</a>
     */
    public function UnchangeOnIndex($index) {
      if (Validator::Validate($index, Validator::INTEGER))
        if ($this->isOpen())
          return $this->class->unchangeIndex($index);
        else
          return FALSE;
    }

    /**
     * Revert all changes done to an entry with the given name.<br />
     *
     * @param string $name Name of the entry.
     *
     * @return boolean TRUE on success or FALSE on failure.<br /><br />
     *
     * @see isOpen()
     * @see <a href="http://be2.php.net/manual/en/function.ziparchive-unchangename.php">unchangeName()</a>
     */
    public function UnchangeOnName($name) {
      if (Validator::Validate($name, Validator::STRING))
        if ($this->isOpen())
          return $this->class->unchangeName($name);
        else
          return FALSE;
    }
  }
?>
